﻿using System;
using System.Collections.Generic;
using System.Linq;
using GalaSoft.MvvmLight;
using System.Windows.Input;
using GalaSoft.MvvmLight.Command;
using RedBranch.Hammock.Design;
using Newtonsoft.Json.Linq;
using System.Windows;
using RedBranch.Hammock;
using System.Collections.ObjectModel;
using CouchAdmin.ViewModel;

namespace CouchAdmin
{
    public class CouchAdminViewModel : ViewModelBase 
    {
        private readonly CouchReplicationRepository _replicationRepo = new CouchReplicationRepository();
        private string _dataBaseName;
        private string _userName;
        private List<string> _databases;
        private string _selectedDatabase;
        private UserViewModel _selectedUser;
        private string _docType;
        private ObservableCollection<UserViewModel> _users;
        private ObservableCollection<DocumentTypeViewModel> _documents; 

        public string DatabaseName
        {
            internal get
            {
                return _dataBaseName;
            }
            set
            {
                _dataBaseName = value;
                RaisePropertyChanged("DatabaseName");
            }
        }

        public string SelectedDatabase
        {
            get
            {
                return _selectedDatabase;
            }
            set
            {
                _selectedDatabase = value;
                RaisePropertyChanged("SelectedDatabase");
                GetUsers(value);
            }
        }

        public UserViewModel SelectedUser
        {
            get
            {
                return _selectedUser;
            }
            set {
                _selectedUser = value;
                RaisePropertyChanged("SelectedUser");
                GetDocuments(value);
            }
        }

        private void GetDocuments(UserViewModel userVm)
        {
            var repository = new Repository<ReplicationDocument>(_replicationRepo.Session);

            var repDocs = (from d in repository.All().ToList()
                           where userVm.Name != null && d.QueryParams["username"].ToString() == userVm.Name
                           select new DocumentTypeViewModel { Name = d.Id.Split('-')[1], username = SelectedUser.Name});
            Documents = new ObservableCollection<DocumentTypeViewModel>(repDocs);
        }

        private void GetUsers(string dbname)
        {
            CouchRepository.Instance.CreateSession(dbname);
            var repository = new Repository<UserViewModel>(CouchRepository.Instance.Session);
            Users = new ObservableCollection<UserViewModel>(repository.All().ToList());
        }

        public string DocType
        {
            get { return _docType; }
            set { 
                _docType = value;
                RaisePropertyChanged("DocType");
            }
        }

        public string UserName
        {
            get
            {
                return _userName;
            }
            set
            {
                _userName = value;
                RaisePropertyChanged("UserName");
            }
        }

        public ObservableCollection<UserViewModel> Users
        {
            get { return _users; }
            set
            {
                _users = value;
                RaisePropertyChanged("Users");
            }
        }

        public ObservableCollection<DocumentTypeViewModel> Documents
        {
            get { return _documents; }
            set { _documents = value;
                RaisePropertyChanged("Documents");
            }
        }

        public List<string> Databases
        {
            get { return _databases; }
            set {
                _databases = value;
                RaisePropertyChanged("Databases");
            }
        }

        public ICommand CreateDatabaseCommand { get; private set; }
        public ICommand AddUserCommand { get; private set; }
        public ICommand AddDocumentCommand { get; private set; }
        public ICommand CreateTestDocuments { get; private set; }

        public CouchAdminViewModel()
        {            
            CreateDatabaseCommand = new RelayCommand(CreateDatabase);
            AddUserCommand = new RelayCommand(CreateUserDoc);
            Databases = CouchRepository.Instance.GetDatabases();
            AddDocumentCommand = new RelayCommand(CreateReplicationDocs);
            CreateTestDocuments = new RelayCommand(CreateTestDocs);
        }

        private void CreateTestDocs()
        {
            var docs = from d in Documents
                       where d.IsSelected
                       select d;

            foreach (var doc in docs)
            {
                CouchRepository.Instance.Session.Save(doc);
            }
        }

        private void CreateDatabase()
        {
            CouchRepository.Instance.CreateDatabase(DatabaseName);
            MessageBox.Show("Database Created Successfully!");
        }

        private void CreateUserDoc()
        {
            CouchRepository.Instance.Session.Save(new UserViewModel {Name = _userName});
            GetUsers(SelectedDatabase);
            RaisePropertyChanged("Users");
        }

        private void CreateReplicationDocs()
        {
            var parm = "{username:" + '"' + SelectedUser.Name + '"' + "}";
            var doc = new ReplicationDocument
            {
                Continuous = true,
                CreateTarget = true,
                Filter = "replicateFilter/clientfilter",
                QueryParams = JObject.Parse(parm),
                Source = "http://localhost:5984/" + SelectedDatabase,
                Target = "http://localhost:5984/master"
            };
            
            CreateDesignDocument();
            if (_replicationRepo.Session != null) if (DocType != null) _replicationRepo.Session.Save(doc, "replicationdocument-" + DocType);
        }

        private void CreateDesignDocument()
        {
            var design = new FilterDocument
            {
                Filters = new Filter { ClientFilter = @"function(doc, req) { if(doc.username == req.query.username) { return true; } return false; }" }
            };
            try
            {
                CouchRepository.Instance.Session.Save(design, "_design/replicateFilter");
            }
            catch (Exception)
            {
            }
        }
    }
}
